package com.bistu.xiong.common.widget;

import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.Toast;

import com.bistu.xiong.common.R;
import com.bistu.xiong.common.app.Application;
import com.bistu.xiong.common.widget.recycler.RecyclerAdapter;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;

import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import static com.bistu.xiong.common.Common.getUriFromDrawable;

/**
 * Created by XiongXiaoJun on 2017/12/18.
 * GalleryView 画廊
 */

public class GalleryView extends RecyclerView {
    // 用于生成Loader
    private static final int LOADER_ID = 0x0100;
    private static final int MAX_IMAGE_COUNT = 9; //最大可选的图片数量
    private static final int MIN_IMAGE_FILE_SIZE = 10*1024; //最小的图片大小
    public static final int ONLY_SHOW_PICS_MODEL = 0x00;
    public static final int CHOOSE_PICS_MODEL = 0x01;
    public static final int SHOW_CHOOSE_PICS_MODEL = 0x02;
    private int CURREN_MODEL = CHOOSE_PICS_MODEL;
    private int column = 4;
    private Adapter mAdapter = new Adapter();
    private List<Image> mSelectedImages = new LinkedList<>();
    private SelectedChangeListener mListener;
    private SelectedAddListener addListener;
    private LoaderCallback mLoaderCallback = new LoaderCallback();

    public GalleryView(Context context) {
        super(context);
        init();
    }

    public GalleryView(Context context,int column,int model) {
        super(context);
        this.column = column;
        CURREN_MODEL = model;
        init();
    }

    public GalleryView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public GalleryView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public void setCurrenModel(int model,int column){
        CURREN_MODEL = model;
        this.column = column;
        setLayoutManager(new GridLayoutManager(getContext(),column));
    }

    private void init() {
        setLayoutManager(new GridLayoutManager(getContext(),column));
        setAdapter(mAdapter);
        mAdapter.setListener(new RecyclerAdapter.AdapterListenerImpl<Image>() {
            @Override
            public void onItemClick(RecyclerAdapter.ViewHolder holder, Image image) {
                //Cell点击操作，如果点击是允许的，那么更新对应的Cell的状态
                //如果不可点击（选择图片已达上限）那么就不刷新界面
                if (CURREN_MODEL==CHOOSE_PICS_MODEL){
                    if(onItemSelectClick(image)){
                        holder.updateData(image);
                    }
                }
                if (CURREN_MODEL==ONLY_SHOW_PICS_MODEL){
                    if (getChildLayoutPosition(holder.itemView)==(mAdapter.getItemCount()-1)){
                        if (addListener!=null){
                            addListener.selectedAdd();
                        }
                    }
                }

            }
        });
    }

    /**
     * Cell点击的具体逻辑
     * @param image
     * @return True表示，进行了数据更改需要刷新操作，反之不刷新
     */
    private boolean onItemSelectClick(Image image){
        //是否需要进行刷新
        boolean notifyRefresh;
        if (mSelectedImages.contains(image)){
            //如果之前已经被选中，那么取消选中，即移除
            mSelectedImages.remove(image);
            image.isSelect = false;
            //状态改变需要刷新
            notifyRefresh = true;
        }else{
            if (mSelectedImages.size()>=MAX_IMAGE_COUNT){
                // 得到提示文字
                String str = getResources().getString(R.string.label_gallery_select_max_size);
                // 格式化填充
                str = String.format(str,MAX_IMAGE_COUNT);
                Toast.makeText(getContext(),str,Toast.LENGTH_SHORT).show();
                notifyRefresh = false;
            }else{
                mSelectedImages.add(image);
                image.isSelect = true;
                notifyRefresh = true;
            }
        }
        //如果数据有更改
        //那么我们需要通知外面的监听者我们的数据选中改变了
        if (notifyRefresh){
            notifySelectChanged();
        }
        return true;
    }

    /**
     * 初始化方法
     * @param loaderManager Loader管理器
     * @return 返回一个LOADER_ID，可用于销毁Loader
     */
    public int setup(LoaderManager loaderManager,SelectedChangeListener listener){
        mListener = listener;
        loaderManager.initLoader(LOADER_ID,null,mLoaderCallback);
        return LOADER_ID;
    }

    /**
     * 得到选中图片的全部地址
     * @return 返回一个数组
     */
    public String[] getSelectedPath(){
        String[] paths = new String[mSelectedImages.size()];
        int index = 0;
        for(Image image:mSelectedImages){
            paths[index++] = image.path;
        }
        return paths;
    }

    /**
     * 可以进行清空选中的图片
     */
    public void clear(){
        for (Image image:mSelectedImages){
            //重置状态
            image.isSelect = false;
        }
        mSelectedImages.clear();
        //通知更新
        mAdapter.notifyDataSetChanged();
    }
    /**
     * 通知选中状态改变
     */
    private void notifySelectChanged(){
        //得到监听者，并判断是否有监听者，然后进行回调数量变化
        SelectedChangeListener listener = mListener;
        if(listener!=null){
            listener.onSelectedCountChanged(mSelectedImages.size());
        }
    }
    /**
     * 通知Adapter数据更改的方法
     * @param images 新的数据
     */
    private void updateSource(List<Image> images){
        mAdapter.replace(images);
    }

    /**
     * 提供给在ONLY_SHOW_PICS_MODEL模式下 直接设置图片
     * @param images
     */
    public void setSource(List<String> images){
        if (images==null)
            images = new ArrayList<>();
        List<Image> imageList = new ArrayList<>();
        for (int i=0;i<images.size();i++){
            if (images.get(i).equals(""))
                continue;
            imageList.add(new Image(images.get(i)));
        }

        updateSource(imageList);
    }

    /**
     * LoaderCallback类
     * 使用loader数据加载
     */
    private class LoaderCallback implements LoaderManager.LoaderCallbacks<Cursor>{
        private final String[] IMAGE_PROJECTION = new String[]{
                MediaStore.Images.Media._ID,  //ID
                MediaStore.Images.Media.DATA,  //图片路径
                MediaStore.Images.Media.DATE_ADDED  //图片的创建时间
        };
        @Override
        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
            //手动创建一个Loader
            //如果是我们的Id则可以进行初始化
            if (id == LOADER_ID){
                //查询图片数据库
                return new CursorLoader(getContext(),
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        IMAGE_PROJECTION,
                        null,
                        null,
                        IMAGE_PROJECTION[2]+" DESC"); //倒序查询
            }
            return null;
        }



        //查询完数据的操作
        @Override
        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
            List<Image> images = new ArrayList<>();
            if (data!=null){
                //移动游标到开始
                data.moveToFirst();
                //得到对应的Index坐标
                int indexId = data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]);
                int indexPath = data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]);
                int indexDate = data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]);
                do{
                    //循环读取，直到没有下一条数据
                    int id = data.getInt(indexId);
                    String path = data.getString(indexPath);
                    long dateTime = data.getLong(indexDate);

                    File file = new File(path);
                    if (!file.exists()||file.length()<MIN_IMAGE_FILE_SIZE){
                        //如果没有图片，或者图片太小
                        continue;
                    }
                    //添加一条新的数据
                    Image image = new Image(id,path,dateTime);
                    images.add(image);
                }while(data.moveToNext());

            }
            updateSource(images);
        }

        @Override
        public void onLoaderReset(Loader<Cursor> loader) {

        }
    }

    /**
     * Image类
     */
    private static class Image{
        int id;              //数据的Id
        String path;         //图片的路径
        long date;          //图片的创建日期
        boolean isSelect;   //是否选中

        public Image() {

        }

        public Image(String path) {
            this.path = path;
        }

        public Image(int id, String path, long date) {
            this.id = id;
            this.path = path;
            this.date = date;
        }

        //覆写equals方法
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Image image = (Image) o;
            return path != null ? path.equals(image.path) : image.path == null;
        }
        //覆写hashCode
        @Override
        public int hashCode() {
            return path != null ? path.hashCode() : 0;
        }
    }

    //*********************适配器部分***********************
    /**
     * 适配器
     */
    private class Adapter extends RecyclerAdapter<Image> {
        @Override
        protected int getItemViewType(int position, Image image) {
            //这里不需要多种子布局
            //如果需要的话 可以根据image对象来返回不同的xml id值
            return R.layout.cell_galley;
        }

        @Override
        protected ViewHolder<Image> onCreateViewHolder(View root, int viewType) {
            return new GalleryView.ViewHolder(root);
        }
    }

    /**
     * Cell 对应的Holder
     */
    private class ViewHolder extends RecyclerAdapter.ViewHolder<Image>{
        private ImageView mPic;
        private View mShade;
        private CheckBox mSelected;

        public ViewHolder(View itemView) {
            super(itemView);

            mPic = (ImageView)itemView.findViewById(R.id.im_image);
            mShade = itemView.findViewById(R.id.view_shade);
            mSelected = (CheckBox)itemView.findViewById(R.id.cb_select);
        }

        @Override
        protected void onBind(Image image) {
            if (CURREN_MODEL==ONLY_SHOW_PICS_MODEL){
                Glide.with(getContext())
                        .load(image.path)
                        .diskCacheStrategy(DiskCacheStrategy.ALL) //因为本机上的图片 所以不需要缓存 直接原图加载
                        .centerCrop() //居中剪切
                        .placeholder(R.color.grey_200) //默认显示
                        .into(mPic);
            }else{
                Glide.with(getContext())
                        .load(image.path)
                        .diskCacheStrategy(DiskCacheStrategy.NONE) //因为本机上的图片 所以不需要缓存 直接原图加载
                        .centerCrop() //居中剪切
                        .placeholder(R.color.grey_200) //默认显示
                        .into(mPic);
            }
            mShade.setVisibility(image.isSelect?VISIBLE:INVISIBLE);
            mShade.setVisibility(CURREN_MODEL==ONLY_SHOW_PICS_MODEL?INVISIBLE:VISIBLE);
            mSelected.setChecked(image.isSelect);
            mSelected.setVisibility(CURREN_MODEL==ONLY_SHOW_PICS_MODEL?INVISIBLE:VISIBLE);

        }
    }

    public void setAddListener(SelectedAddListener addListener) {
        this.addListener = addListener;
    }

    /**
     * 对外的一个监听器
     */
    public interface SelectedChangeListener{
        void onSelectedCountChanged(int count);
    }
    public interface SelectedAddListener{
        void selectedAdd();
    }
}
